package util.network;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class ClientServerAndroidActivity extends Activity {
    /** Called when the activity is first created. */
	
	private EditText textOut, textIp;
	private TextView textIn;
	private Button buttonServer, buttonSend;
	
	private List<String> connections;
	private List<List<String>> serverAnswers;
	
	private boolean isServer = false;
	private String ip="0.0.0.0";
	
	private Handler handler;
	private Thread client, server;
	
	private String clientMessage="";
	private String serverMessage="";
	private String message="";
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        textIp = (EditText)findViewById(R.id.editTextIP);
        textOut = (EditText)findViewById(R.id.editText1);
        textIn = (TextView)findViewById(R.id.textView1);
        buttonSend = (Button)findViewById(R.id.button1);
        buttonServer = (Button)findViewById(R.id.buttonServer);
        
        textIp.addTextChangedListener(textIpTextChangedListener);
        buttonSend.setOnClickListener(buttonSendOnClickListener);
        buttonServer.setOnClickListener(buttonServerOnClickListener);
        textIn.setMovementMethod(new ScrollingMovementMethod());
        
        handler=new Handler();
        connections = new LinkedList<String>();
        serverAnswers = new LinkedList<List<String>>();
    }
    
    @Override
    public void onStop(){
    	super.onDestroy();
    	isServer=!isServer;
    	stopThreads();
    }
    public void getIP(View v){
    	Runnable runnable = new Runnable(){
			@Override
			public void run() {
				try {
			        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
			            NetworkInterface intf = en.nextElement();
			            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
			                InetAddress inetAddress = enumIpAddr.nextElement();
			                if (!inetAddress.isLoopbackAddress()) {
			                    ip = inetAddress.getHostAddress().toString();
			                }
			            }
			        }
			    } catch (SocketException e) {
			       e.printStackTrace();
			    }
			    /* Esto te devuelve la ip localhost
				try{
			    	InetAddress addr=InetAddress.getLocalHost();
			    	// ip=addr.getAddress().toString();
			    	// ip=addr.getHostName()
			    	ip=addr.getHostAddress();
			    }catch (UnknownHostException e){
			    	e.printStackTrace();
			    }*/
				handler.post(new Runnable(){
					@Override
					public void run() {
						buttonServer.setText("Servidor: " + ip);						
					}
				});
			}
    	};
    	new Thread(runnable).start();
    }
    
    public void serverJob(){    	
    	Runnable runnable = new Runnable(){
    		DataInputStream in=null;
			DataOutputStream out=null;
			Socket socket=null;
			ServerSocket serverSocket=null;
	    	
			@Override
			public void run() {
				try {
					serverSocket = new ServerSocket(8888);
					System.out.println("Listening: 8888");
					isServer=true;
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				while(isServer){
					try {
						socket = serverSocket.accept();
					    in = new DataInputStream(socket.getInputStream());
					    out = new DataOutputStream(socket.getOutputStream());
					    if(!connections.contains(socket.getInetAddress().toString())){
					    	connections.add(socket.getInetAddress().toString());
					    	serverAnswers.add(new LinkedList<String>());
					    }

					    serverMessage=in.readUTF();
						if(serverMessage.equals("rq@")){ //send
							serverMessage="";
							for(int c=0;c<connections.size();c++){
								if(connections.get(c).equals(socket.getInetAddress().toString()))
									if(serverAnswers.size()>c){									
										if(!serverAnswers.get(c).isEmpty()){
										clientMessage="\nip: " + ip;
										for(int a=0; a<serverAnswers.get(c).size();a++)
											clientMessage+="\nmessage: " + serverAnswers.get(c).get(a);
										serverAnswers.get(c).clear();
										
										out.writeUTF(clientMessage);
									}}
							}
						}else if(serverMessage.startsWith("msg@")) //receive 
							serverMessage=serverMessage.substring(4);
					    
					handler.post(new Runnable(){
						@Override
						public void run() {
							//textIn.setText(textIn.getText() + "\nCC: " + connections.toString()+"-SS: "+socket.getInetAddress().toString());
							if(!serverMessage.isEmpty() && !serverMessage.equals("rq@")){
								textIn.setText(textIn.getText()+"\nip: " + socket.getInetAddress());
								textIn.setText(textIn.getText()+"\nmessage: " + serverMessage);
							}
						}
					});
					} catch (IOException e) {
						e.printStackTrace();
					}finally{
						if (socket != null){
				    		try {
				    			socket.close();
				    		} catch (IOException e){
				    			e.printStackTrace();
				    		}
				    	}
				
				    	if (out != null){
				    		try {
				    			out.close();
				    		} catch (IOException e) {
				    			e.printStackTrace()	;
				    		}
				    	}
				
				    	if (in != null){
				    		try {
				    			in.close();
				    		} catch (IOException e) {
				    			e.printStackTrace();
				    		}
				    	}
					} //finally
				} //while
			} //run
    	};
    	server = new Thread(runnable);
    	server.start();
    }
    
    public void clientJob(){
    	Runnable runnable = new Runnable(){
    		DataInputStream dataInputStream=null;
			DataOutputStream dataOutputStream=null;
			Socket socket=null;
			@Override
			public void run() {
				while(!isServer){
					try {
						if(!isServer){
							try {
								Thread.sleep(5000);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
							ip=textIp.getText().toString();
							if(ip.matches("[0-9]{0,3}.[0-9]{0,3}.[0-9]{0,3}.[0-9]{0,3}")){
								socket = new Socket(ip, 8888);
								dataOutputStream = new DataOutputStream(socket.getOutputStream());
								dataOutputStream.writeUTF("rq@");
								dataInputStream = new DataInputStream(socket.getInputStream());
								message=dataInputStream.readUTF();
							}else message="";
						}
						handler.post(new Runnable(){
							@Override
							public void run() {
							    if(!isServer && !message.isEmpty())
							    	textIn.setText(textIn.getText()+"\n"+message);
							}
						});
					} catch (UnknownHostException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
				    finally{
				    	if (socket != null){
				    		try {
				    			socket.close();
				    		} catch (IOException e){
				    			e.printStackTrace();
				    		}
				    	}
				
				    	if (dataOutputStream != null){
				    		try {
				    			dataOutputStream.close();
				    		} catch (IOException e) {
				    			e.printStackTrace()	;
				    		}
				    	}
				
				    	if (dataInputStream != null){
				    		try {
				    			dataInputStream.close();
				    		} catch (IOException e) {
				    			e.printStackTrace();
				    		}
				    	}
				    }//finally
				}//while
			}//run
    	};
    	client = new Thread(runnable);
    	client.start();
    }
    
    public void sendMessage(){
    	Runnable runnable = new Runnable(){
    		DataInputStream dataInputStream=null;
			DataOutputStream dataOutputStream=null;
			Socket s=null;
			@Override
			public void run() {
				if(isServer){
					for(int c=0; c<connections.size();c++){
						if(serverAnswers.size()>0){
							if(serverAnswers.get(c)==null)
								serverAnswers.set(c, new LinkedList<String>());
							serverAnswers.get(c).add(textOut.getText().toString());
						}else{
							
						}
					}
				}else{//Client
					try {					
						ip=textIp.getText().toString();
						if(ip.matches("[0-9]{0,3}.[0-9]{0,3}.[0-9]{0,3}.[0-9]{0,3}")){
							s = new Socket(ip, 8888);
							dataOutputStream = new DataOutputStream(s.getOutputStream());
							dataOutputStream.writeUTF("msg@"+textOut.getText().toString());
						}
					} catch (UnknownHostException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
					finally{
						if (s != null){
							try {
								s.close();
				    		} catch (IOException e){
				    			e.printStackTrace();
				    		}
				    	}
				
				    	if (dataOutputStream != null){
				    		try {
				    			dataOutputStream.close();
				    		} catch (IOException e) {
				    			e.printStackTrace()	;
				    		}
				    	}
				
				    	if (dataInputStream != null){
				    		try {
				    			dataInputStream.close();
				    		} catch (IOException e) {
				    			e.printStackTrace();
				    		}
				    	}
				    }//finally
				}//else client
			}//run
    	};
    	new Thread(runnable).start();
    }
    
    public void stopThreads(){
    	Thread s,c;
    	c=client;
    	s=server;
    	client=null;
    	server=null;
    	if(s!=null)
    		s.interrupt();
    	if(c!=null)
    		c.interrupt();
    }
    
    Button.OnClickListener buttonServerOnClickListener = new Button.OnClickListener(){
		@Override
		public void onClick(View v) {	
			stopThreads();
			
			getIP(v);
			serverJob();
			
		}
    };
    
	Button.OnClickListener buttonSendOnClickListener = new Button.OnClickListener(){
	@Override
	public void onClick(View v) {
		if(!textOut.getText().toString().isEmpty()){
			System.out.println("Sending Message: " + textOut.getText().toString());
			sendMessage();
		}
	}};
	
	TextWatcher textIpTextChangedListener = new TextWatcher(){
		@Override
		public void afterTextChanged(Editable s) {
			isServer=false;
			buttonServer.setText("Servidor");
			stopThreads();
			clientJob();
		}

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {
			
		}

		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
			
		}
	};
    
}